home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / nfs / nfswatch4.0 / nfswatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-01  |  24.6 KB  |  1,257 lines

  1. #ifndef lint
  2. static char *RCSid = "$Header: /home/harbor/davy/system/nfswatch/RCS/nfswatch.c,v 4.0 1993/03/01 19:59:00 davy Exp $";
  3. #endif
  4.  
  5. #include "os.h"
  6.  
  7. /*
  8.  * nfswatch - NFS server packet monitoring program.
  9.  *
  10.  * David A. Curry                Jeffrey C. Mogul
  11.  * Purdue University                Digital Equipment Corporation
  12.  * Engineering Computer Network            Western Research Laboratory
  13.  * 1285 Electrical Engineering Building        250 University Avenue
  14.  * West Lafayette, IN 47907-1285        Palo Alto, CA 94301
  15.  * davy@ecn.purdue.edu                mogul@decwrl.dec.com
  16.  *
  17.  * $Log: nfswatch.c,v $
  18.  * Revision 4.0  1993/03/01  19:59:00  davy
  19.  * NFSWATCH Version 4.0.
  20.  *
  21.  * Revision 3.13  1993/02/24  17:44:45  davy
  22.  * Added -auth mode, changes to -proc mode, -map option, -server option.
  23.  *
  24.  * Revision 3.12  1993/01/20  14:52:30  davy
  25.  * Added -T maxtime option.
  26.  *
  27.  * Revision 3.11  1993/01/16  19:08:59  davy
  28.  * Corrected Jeff's address.
  29.  *
  30.  * Revision 3.10  1993/01/15  22:09:20  davy
  31.  * Fixed for Sun FDDI using the NIT.
  32.  *
  33.  * Revision 3.9  1993/01/15  19:33:39  davy
  34.  * Miscellaneous cleanups.
  35.  *
  36.  * Revision 3.8  1993/01/15  15:43:36  davy
  37.  * Assorted changes for porting to Solaris 2.x/SVR4.
  38.  *
  39.  * Revision 3.7  1993/01/14  15:51:16  davy
  40.  * Added FDDI code and device type calculation to NIT and SNOOP.  The FDDI
  41.  * stuff almost definitely won't work without modification on the SNOOP
  42.  * side; it still needs to be tested on the NIT side.
  43.  *
  44.  * Revision 3.6  1993/01/13  21:24:19  davy
  45.  * Assorted changes for porting to IRIX.
  46.  *
  47.  * Revision 3.5  1993/01/13  20:18:17  davy
  48.  * Put in OS-specific define scheme, and merged in Tim Hudson's code for
  49.  * SGI systems (as yet untested).
  50.  *
  51.  * Revision 3.4  1993/01/13  18:59:30  davy
  52.  * Changed sigvec calls to signal calls, for portability to other os versions.
  53.  *
  54.  * Revision 3.3  1993/01/13  15:12:05  davy
  55.  * Added background mode.
  56.  *
  57.  * Revision 3.2  1992/07/24  18:47:57  mogul
  58.  * Added FDDI support
  59.  *
  60.  * Revision 3.1  1991/01/23  16:56:19  mogul
  61.  * Black magic
  62.  *
  63.  * Revision 3.1  1991/01/23  16:56:19  mogul
  64.  * Black magic
  65.  *
  66.  * Revision 3.0  91/01/23  08:23:11  davy
  67.  * NFSWATCH Version 3.0.
  68.  * 
  69.  * Revision 1.5  91/01/04  16:05:15  davy
  70.  * Updated version number.
  71.  * 
  72.  * Revision 1.4  91/01/04  15:54:29  davy
  73.  * New features from Jeff Mogul.
  74.  * 
  75.  * Revision 1.3  90/12/04  08:06:41  davy
  76.  * Changed version number to 2.1.
  77.  * 
  78.  * Revision 1.2  90/08/17  15:47:29  davy
  79.  * NFSWATCH Version 2.0.
  80.  * 
  81.  * Revision 1.1  88/11/29  11:20:40  davy
  82.  * NFSWATCH Release 1.0
  83.  * 
  84.  */
  85. #include <sys/param.h>
  86. #include <sys/socket.h>
  87. #include <sys/ioctl.h>
  88. #include <sys/time.h>
  89. #include <net/if.h>
  90. #include <signal.h>
  91. #include <errno.h>
  92. #include <stdio.h>
  93.  
  94. #ifdef USE_DLPI
  95. #include <sys/stream.h>
  96. #include <sys/stropts.h>
  97.  
  98. #if defined(SVR4) && !defined(SUNOS5)
  99. char    *devices[] = {
  100.     "emd0", "emd1", "emd2", "emd3", "emd4",
  101.     0
  102. };
  103. #endif
  104.  
  105. #ifdef SUNOS5
  106. #include <sys/bufmod.h>
  107.  
  108. char    *devices[] = {
  109.     "le0", "le1", "le2", "le3", "le4",
  110.     "ie0", "ie1", "ie2", "ie3", "ie4",
  111.     "fddi0", "fddi1", "fddi2", "fddi3", "fddi4",
  112.     0
  113. };
  114. #endif
  115. #endif /* USE_DLPI */
  116.  
  117. #ifdef USE_NIT
  118. #include <net/nit_if.h>
  119. #include <net/nit_buf.h>
  120.  
  121. char    *devices[] = {
  122.     "le0", "le1", "le2", "le3", "le4",
  123.     "ie0", "ie1", "ie2", "ie3", "ie4",
  124.     "fddi0", "fddi1", "fddi2", "fddi3", "fddi4",
  125.     0
  126. };
  127.  
  128. #endif /* USE_NIT */
  129.  
  130. #ifdef USE_PFILT
  131. #include <net/pfilt.h>
  132.  
  133. char    *devices[] = {
  134.     "pf0", "pf1", "pf2", "pf3", "pf4", "pf5",
  135.     "pf6", "pf7", "pf8", "pf9",
  136.     0
  137. };
  138. #endif /* USE_PFILT */
  139.  
  140. #ifdef USE_SNOOP
  141. #include <net/soioctl.h>
  142. #include <net/raw.h>
  143. #include <netinet/if_ether.h>
  144.  
  145. #define ETHERHDRPAD        RAW_HDRPAD(sizeof(struct ether_header))
  146.  
  147. char    *devices[] = {
  148.     "et0", "et1", "et2", "et3", "et4",
  149.     "ec0", "ec1", "ec2", "ec3", "ec4",
  150.     "fxp0", "fxp1", "fxp2", "fxp3", "fxp4",
  151.     "enp0", "enp1", "enp2", "enp3", "enp4",
  152.     "ipg0", "ipg1", "ipg2", "ipg3", "ipg4",
  153.     0
  154. };
  155.  
  156. struct etherpacket {
  157.     struct snoopheader    snoop;
  158.     char            pad[ETHERHDRPAD];
  159.     struct ether_header    ether;
  160.     char            data[ETHERMTU];
  161. };
  162. #endif /* USE_SNOOP */
  163.  
  164. #include "nfswatch.h"
  165.  
  166. char        *pname;                /* program name        */
  167.  
  168. FILE        *logfp;                /* log file pointer    */
  169.  
  170. Counter        pkt_total = 0;            /* total packets seen    */
  171. Counter        pkt_drops = 0;            /* total packets dropped*/
  172. Counter        int_pkt_total = 0;        /* packets this interval*/
  173. Counter        int_pkt_drops = 0;        /* dropped this interval*/
  174. Counter        dst_pkt_total = 0;        /* total pkts to host    */
  175. Counter        int_dst_pkt_total = 0;        /* pkts to host this int*/
  176.  
  177. int        if_fd[MAXINTERFACES];        /* LAN device file desc    */
  178. int        if_dlt[MAXINTERFACES];        /* LAN data link type    */
  179.  
  180. int        bgflag = 0;            /* "-bg" specified    */
  181. int        srcflag = 0;            /* "-src" specified    */
  182. int        dstflag = 0;            /* "-dst" specified    */
  183. int        allflag = 0;            /* "-all" specified    */
  184. int        allintf = 0;            /* "-allif" specified    */
  185. int        logging = 0;            /* 1 when logging on    */
  186. int        learnfs = 0;            /* learn other servers    */
  187. int        do_update = 0;            /* time to update screen*/
  188. int        showwhich = 0;            /* show filesys or files*/
  189. int        serverflag = 0;            /* "-server" specified    */
  190. int        cycletime = CYCLETIME;        /* update cycle time    */
  191. int        totaltime = 0;            /* total run time    */
  192. int        truncation = 200;        /* pkt trunc len - magic*/
  193. int        sortbyusage = 0;        /* sort by usage counts    */
  194. int        nnfscounters = 0;        /* # of NFS counters    */
  195. int        nfilecounters = 0;        /* # of file counters    */
  196. int        nauthcounters = 0;        /* # of auth counters    */
  197. int        nclientcounters = 0;        /* # of client counters */
  198. int        screen_inited = 0;        /* 1 when in curses    */
  199.  
  200. struct timeval    starttime;            /* time we started    */
  201.  
  202. int        ninterfaces;            /* number of interfaces    */
  203.  
  204. u_long        thisdst = 0;            /* cached IP dst of pkt    */
  205. u_long        srcaddrs[MAXHOSTADDR];        /* src host net addrs    */
  206. u_long        dstaddrs[MAXHOSTADDR];        /* dst host net addrs    */
  207. u_long        serveraddrs[MAXHOSTADDR];    /* server host net addrs*/
  208.  
  209. char        myhost[MAXHOSTNAMELEN];        /* local host name    */
  210. char        srchost[MAXHOSTNAMELEN];    /* source host name    */
  211. char        dsthost[MAXHOSTNAMELEN];    /* destination host name*/
  212. char        serverhost[MAXHOSTNAMELEN];    /* server host name    */
  213.  
  214. char        *prompt = PROMPT;        /* prompt string    */
  215. char        *filelist = NULL;        /* list of files    */
  216. char        *logfile = LOGFILE;        /* log file name    */
  217. char        *mapfile = NULL;        /* map file name    */
  218. char        *snapshotfile = SNAPSHOTFILE;    /* snapshot file name    */
  219.  
  220. NFSCounter    nfs_counters[MAXEXPORT];    /* NFS request counters    */
  221. FileCounter    fil_counters[MAXEXPORT];    /* file request counters*/
  222. PacketCounter    pkt_counters[PKT_NCOUNTERS];    /* packet counters    */
  223. ProcCounter    prc_counters[MAXNFSPROC+2];    /* procedure counters    */
  224.                 /* extra space simplifies sort_prc_counters */
  225. int        prc_countmap[MAXNFSPROC];    /* allows sorting    */
  226. ClientCounter    clnt_counters[MAXCLIENTS];    /* per-client counters    */
  227. AuthCounter    auth_counters[MAXAUTHS];    /* per-auth counters    */
  228.  
  229. extern void finish();
  230.  
  231. #ifdef ultrix
  232. void
  233. fpe_warn()
  234. {
  235.     fprintf(stderr, "nfswatch: mystery bug encountered.\n");
  236.     finish(-1);
  237. }
  238. #endif
  239.  
  240. main(argc, argv)
  241. int argc;
  242. char **argv;
  243. {
  244.     register int i;
  245.     char *device = NULL;
  246.     extern void nfswatch();
  247.  
  248.     pname = *argv;
  249.  
  250.     /*
  251.      * Get our host name.  The default destination
  252.      * host is the one we're running on.
  253.      */
  254.     if (gethostname(myhost, sizeof(myhost)) < 0) {
  255.         error("gethostname");
  256.         finish(-1);
  257.     }
  258.  
  259.     (void) strcpy(dsthost, myhost);
  260.  
  261.     /*
  262.      * Process arguments.
  263.      */
  264.     while (--argc) {
  265.         if (**++argv != '-')
  266.             usage();
  267.  
  268.         /*
  269.          * Set destination host.
  270.          */
  271.         if (!strcmp(*argv, "-dst")) {
  272.             if (--argc <= 0)
  273.                 usage();
  274.  
  275.             (void) strcpy(dsthost, *++argv);
  276.             dstflag++;
  277.             continue;
  278.         }
  279.  
  280.         /*
  281.          * Set source host.
  282.          */
  283.         if (!strcmp(*argv, "-src")) {
  284.             if (--argc <= 0)
  285.                 usage();
  286.  
  287.             (void) strcpy(srchost, *++argv);
  288.             srcflag++;
  289.             continue;
  290.         }
  291.  
  292.         /*
  293.          * Set server host.
  294.          */
  295.         if (!strcmp(*argv, "-server")) {
  296.             if (--argc <= 0)
  297.                 usage();
  298.  
  299.             (void) strcpy(serverhost, *++argv);
  300.             serverflag++;
  301.             continue;
  302.         }
  303.  
  304.         /*
  305.          * Device to use.
  306.          */
  307.         if (!strcmp(*argv, "-dev")) {
  308.             if (--argc <= 0)
  309.                 usage();
  310.  
  311.             device = *++argv;
  312.             continue;
  313.         }
  314.  
  315.         /*
  316.          * Log file name.
  317.          */
  318.         if (!strcmp(*argv, "-lf")) {
  319.             if (--argc <= 0)
  320.                 usage();
  321.  
  322.             logfile = *++argv;
  323.             continue;
  324.         }
  325.  
  326.         /*
  327.          * Snapshot file name.
  328.          */
  329.         if (!strcmp(*argv, "-sf")) {
  330.             if (--argc <= 0)
  331.                 usage();
  332.  
  333.             snapshotfile = *++argv;
  334.             continue;
  335.         }
  336.  
  337.         /*
  338.          * List of files.
  339.          */
  340.         if (!strcmp(*argv, "-f")) {
  341.             if (--argc <= 0)
  342.                 usage();
  343.  
  344.             if (showwhich == 0)
  345.                 showwhich = SHOWINDVFILES;
  346.  
  347.             filelist = *++argv;
  348.             continue;
  349.         }
  350.  
  351.         /*
  352.          * Set map file.
  353.          */
  354.         if (!strcmp(*argv, "-map")) {
  355.             if (--argc <= 0)
  356.                 usage();
  357.  
  358.             mapfile = *++argv;
  359.             continue;
  360.         }
  361.         
  362.         /*
  363.          * Set total run time.
  364.          */
  365.         if (!strcmp(*argv, "-T")) {
  366.             if (--argc <= 0)
  367.                 usage();
  368.             
  369.             totaltime = atoi(*++argv);
  370.             continue;
  371.         }
  372.  
  373.         /*
  374.          * Change cycle time.
  375.          */
  376.         if (!strcmp(*argv, "-t")) {
  377.             if (--argc <= 0)
  378.                 usage();
  379.  
  380.             cycletime = atoi(*++argv);
  381.             continue;
  382.         }
  383.  
  384.         /*
  385.          * Show RPC authentication.
  386.          */
  387.         if (!strcmp(*argv, "-auth")) {
  388.             showwhich = SHOWAUTH;
  389.             continue;
  390.         }
  391.  
  392.         /*
  393.          * Show file systems.
  394.          */
  395.         if (!strcmp(*argv, "-fs")) {
  396.             showwhich = SHOWFILESYSTEM;
  397.             continue;
  398.         }
  399.  
  400.         /*
  401.          * Show individual files.
  402.          */
  403.         if (!strcmp(*argv, "-if")) {
  404.             showwhich = SHOWINDVFILES;
  405.             continue;
  406.         }
  407.  
  408.         /*
  409.          * Show NFS procedures
  410.          */
  411.         if (!strcmp(*argv, "-procs")) {
  412.             showwhich = SHOWNFSPROCS;
  413.             continue;
  414.         }
  415.  
  416.         /*
  417.          * Show NFS clients
  418.          */
  419.         if (!strcmp(*argv, "-clients")) {
  420.             showwhich = SHOWCLIENTS;
  421.             continue;
  422.         }
  423.  
  424.         /*
  425.          * Turn on logging.
  426.          */
  427.         if (!strcmp(*argv, "-l")) {
  428.             logging++;
  429.             continue;
  430.         }
  431.  
  432.         /*
  433.          * Run in background mode.
  434.          */
  435.         if (!strcmp(*argv, "-bg")) {
  436.             logging++;
  437.             bgflag++;
  438.             continue;
  439.         }
  440.  
  441.         /*
  442.          * Watch all traffic.
  443.          */
  444.         if (!strcmp(*argv, "-all")) {
  445.             allflag++;
  446.             continue;
  447.         }
  448.  
  449.         /*
  450.          * Use all interfaces.
  451.          */
  452.         if (!strcmp(*argv, "-allif")) {
  453.             allintf++;
  454.             continue;
  455.         }
  456.  
  457.         /*
  458.          * Sort file systems by usage, not name.
  459.          */
  460.         if (!strcmp(*argv, "-usage")) {
  461.             sortbyusage++;
  462.             continue;
  463.         }
  464.  
  465.         usage();
  466.     }
  467.  
  468.     /*
  469.      * Check what we're showing.
  470.      */
  471.     switch (showwhich) {
  472.     case 0:            /* default */
  473.         showwhich = SHOWFILESYSTEM;
  474.         break;
  475.     case SHOWINDVFILES:
  476.         if (filelist == NULL) {
  477.             (void) fprintf(stderr, "%s: must specify file list with -fi.\n", pname);
  478.             finish(-1);
  479.         }
  480.  
  481.         break;
  482.     }
  483.  
  484.     /*
  485.      * Trap signals so we can clean up.
  486.      */
  487.     (void) signal(SIGINT, finish);
  488.     (void) signal(SIGQUIT, finish);
  489.     (void) signal(SIGTERM, finish);
  490.  
  491. #ifdef sgi
  492.     /*
  493.      * Kludge to prevent coredumps when the optimizer's on?
  494.      */
  495.     (void) signal(SIGFPE, SIG_IGN);
  496. #endif
  497.  
  498. #ifdef ultrix
  499.     (void) signal(SIGFPE, fpe_warn);
  500. #endif
  501.  
  502. #ifdef USE_DLPI
  503.     /*
  504.      * Set up the data link interface provider  right away,
  505.      * since we probably need super-user permission.
  506.      */
  507.     if (allintf) {
  508.         ninterfaces = 0;
  509.         for (i=0; devices[i] != NULL; i++) {
  510.         if_fd[ninterfaces] = setup_dlpi_dev(&devices[i]);
  511.  
  512.         if (if_fd[ninterfaces] >= 0) {
  513.             if_dlt[ninterfaces] = dlpi_devtype(if_fd[ninterfaces]);
  514.             ninterfaces++;
  515.         }
  516.         }
  517.     }
  518.     else {
  519.         if_fd[0] = setup_dlpi_dev(&device);
  520.  
  521.         if (if_fd[0] < 0) {
  522.         error(device);
  523.         finish(-1);
  524.         }
  525.  
  526.         if_dlt[0] = dlpi_devtype(if_fd[0]);
  527.         ninterfaces = 1;
  528.     }
  529. #endif /* USE_DLPI */
  530.  
  531. #ifdef USE_NIT
  532.     /*
  533.      * Set up the network interface tap right away,
  534.      * since we probably need super-user permission.
  535.      */
  536.     if (allintf) {
  537.         ninterfaces = 0;
  538.         for (i=0; devices[i] != NULL; i++) {
  539.         if_fd[ninterfaces] = setup_nit_dev(&devices[i]);
  540.  
  541.         if (if_fd[ninterfaces] >= 0) {
  542.             if_dlt[ninterfaces] = nit_devtype(devices[i]);
  543.             ninterfaces++;
  544.         }
  545.         }
  546.     }
  547.     else {
  548.         if_fd[0] = setup_nit_dev(&device);
  549.  
  550.         if (if_fd[0] < 0) {
  551.         error(device);
  552.         finish(-1);
  553.         }
  554.  
  555.         if_dlt[0] = nit_devtype(device);
  556.         ninterfaces = 1;
  557.     }
  558. #endif /* USE_NIT */
  559.  
  560. #ifdef USE_PFILT
  561.     /*
  562.      * Set up the packet filter interface now,
  563.      * although we don't need super-user permission.
  564.      */
  565.     if (allintf) {
  566.         ninterfaces = 0;
  567.         for (i=0; devices[i] != NULL; i++) {
  568.         if_fd[ninterfaces] = setup_pfilt_dev(&devices[i]);
  569.  
  570.         if (if_fd[ninterfaces] >= 0) {
  571.             if_dlt[ninterfaces] = pfilt_devtype(if_fd[ninterfaces]);
  572.             ninterfaces++;
  573.         }
  574.         }
  575.     }
  576.     else {
  577.         if_fd[0] = setup_pfilt_dev(&device);
  578.  
  579.         if (if_fd[0] < 0) {
  580.         error(device);
  581.         finish(-1);
  582.         }
  583.  
  584.         if_dlt[0] = pfilt_devtype(if_fd[0]);
  585.         ninterfaces = 1;
  586.     }
  587. #endif /* USE_PFILT */
  588.  
  589. #ifdef USE_SNOOP
  590.     /*
  591.      * Set up the snoop interface right away,
  592.      * since we probably need super-user permission.
  593.      */
  594.     if (allintf) {
  595.         ninterfaces = 0;
  596.         for (i=0; devices[i] != NULL; i++) {
  597.         if_fd[ninterfaces] = setup_snoop_dev(&devices[i]);
  598.  
  599.         if (if_fd[ninterfaces] >= 0) {
  600.             if_dlt[ninterfaces] = snoop_devtype(devices[i]);
  601.             ninterfaces++;
  602.         }
  603.         }
  604.     }
  605.     else {
  606.         if_fd[0] = setup_snoop_dev(&device);
  607.  
  608.         if (if_fd[0] < 0) {
  609.         error(device);
  610.         finish(-1);
  611.         }
  612.  
  613.         if_dlt[0] = snoop_devtype(device);
  614.         ninterfaces = 1;
  615.     }
  616. #endif /* USE_SNOOP */
  617.  
  618.     if (ninterfaces < 1) {
  619.         fprintf(stderr, "%s: no valid interfaces.\n", pname);
  620.         finish(-1);
  621.     }
  622.  
  623.     /*
  624.      * Now lose super-user permission, since we
  625.      * don't need it for anything else.
  626.      */
  627. #ifdef SVR4
  628.     (void) setuid(getuid());
  629.     (void) seteuid(getuid());
  630. #else
  631.     (void) setreuid(getuid(), getuid());
  632. #endif
  633.  
  634.     /*
  635.      * Look up the network addresses of the source and
  636.      * destination hosts.
  637.      */
  638.     get_net_addrs();
  639.  
  640.     /*
  641.      * Tell the user what's going on.
  642.      */
  643.     (void) printf("NFSWATCH Version %s\n", VERSION);
  644.  
  645.     if (serverflag) {
  646.         (void) printf("Watch packets to/from %s on ", serverhost);
  647.     }
  648.     else {
  649.         (void) printf("Watch packets from %s to %s on ",
  650.                   (srcflag ? srchost : "all hosts"), dsthost);
  651.     }
  652.  
  653.     if (allintf)
  654.         (void) printf("all interfaces;\n");
  655.     else {
  656.         (void) printf("%s ", dlt_name(if_dlt[0]));
  657.         (void) printf("interface %s;\n", device);
  658.     }
  659.  
  660.     (void) printf("log to \"%s\" (logging %s);\n", logfile,
  661.         (logging ? "on" : "off"));
  662.  
  663.     if (bgflag) {
  664.         (void) printf("cycle time %d seconds;\n", cycletime);
  665.         (void) printf("running as a daemon in the background...");
  666.     }
  667.     else {
  668.         (void) printf("snapshots to \"%s\";\n", snapshotfile);
  669.         (void) printf("cycle time %d seconds...", cycletime);
  670.     }
  671.  
  672.     (void) fflush(stdout);
  673.  
  674.     /*
  675.      * No more informational output, so fork and exit if in
  676.      * background mode.
  677.      */
  678.     if (bgflag) {
  679.         int pid;
  680.  
  681.         if ((pid = fork()) < 0) {
  682.             error("fork");
  683.             finish(-1);
  684.         }
  685.  
  686.         if (pid != 0) {
  687.             printf("pid = %d\n", pid);
  688.             exit(0);
  689.         }
  690.     }
  691.  
  692.     /*
  693.      * Set up a pseudo RPC server.
  694.      */
  695.     setup_rpcxdr();
  696.  
  697.     /*
  698.      * Set up the screen.
  699.      */
  700.     if (!bgflag)
  701.         setup_screen(device);
  702.  
  703.     /*
  704.      * Set up the packet counters.  This must be done after
  705.      * setup_screen because they use the LINES variable.
  706.      */
  707.     setup_pkt_counters();
  708.     setup_nfs_counters();
  709.     setup_proc_counters();
  710.  
  711.     if (filelist)
  712.         setup_fil_counters();
  713.  
  714.     if (mapfile)
  715.         setup_map_file();
  716.  
  717.     /*
  718.      * Now label the screen.
  719.      */
  720.     if (!bgflag)
  721.         label_screen();
  722.  
  723.     /*
  724.      * Open log file if logging is on.
  725.      */
  726.     if (logging) {
  727.         if ((logfp = fopen(logfile, "a")) == NULL) {
  728.             error(logfile);
  729.             finish(-1);
  730.         }
  731.  
  732.         (void) fprintf(logfp, "#\n# startlog\n#\n");
  733.         (void) fprintf(logfp, "# NFSwatch log file\n");
  734.         (void) fprintf(logfp, "#    Packets from: %s\n",
  735.             (srcflag ? srchost : "all hosts"));
  736.         (void) fprintf(logfp, "#    Packets to:   %s\n#\n",
  737.             dsthost);
  738.     }
  739.  
  740.     /*
  741.      * Go watch packets.  Never returns.
  742.      */
  743.     nfswatch();
  744. }
  745.  
  746. /*
  747.  * nfswatch - main packet reading loop.
  748.  */
  749. void
  750. nfswatch()
  751. {
  752.     int i, cc;
  753.     char *buf;
  754.     char *malloc();
  755.     fd_set readfds;
  756.     struct timeval tv;
  757.     extern void wakeup();
  758.     struct itimerval itv;
  759.     register char *bp, *cp, *bufstop;
  760. #ifdef USE_DLPI
  761.     int tdrops[MAXINTERFACES];
  762.     struct strbuf strdata;
  763.     struct sb_hdr *hdrp;
  764.     int flags;
  765. #endif
  766. #ifdef USE_NIT
  767.     int tdrops[MAXINTERFACES];
  768.     struct nit_iftime *tstamp;
  769.     struct nit_bufhdr *hdrp;
  770.     struct nit_ifdrops *ndp;
  771. #endif
  772. #ifdef USE_PFILT
  773.     struct enstamp stamp;
  774.     int datalen;
  775. #endif
  776. #ifdef USE_SNOOP
  777.     int tdrops[MAXINTERFACES];
  778.     struct etherpacket ep;
  779.     struct rawstats rs;
  780. #endif
  781.  
  782. #ifdef USE_DLPI
  783.     /*
  784.      * Allocate a buffer so it's properly aligned for
  785.      * casting to structure types.
  786.      */
  787.     if ((buf = malloc(DLPI_CHUNKSIZE)) == NULL) {
  788.         (void) fprintf(stderr, "%s: out of memory.\n", pname);
  789.         finish(-1);
  790.     }
  791.  
  792.     strdata.len = 0;
  793.     strdata.buf = buf;
  794.     strdata.maxlen = DLPI_CHUNKSIZE;
  795. #endif
  796.  
  797. #ifdef USE_NIT
  798.     /*
  799.      * Allocate a buffer so it's properly aligned for
  800.      * casting to structure types.
  801.      */
  802.     if ((buf = malloc(NIT_CHUNKSIZE)) == NULL) {
  803.         (void) fprintf(stderr, "%s: out of memory.\n", pname);
  804.         finish(-1);
  805.     }
  806. #endif
  807.  
  808. #ifdef USE_PFILT
  809.     /*
  810.      * Allocate a buffer so it's properly aligned for
  811.      * casting to structure types.
  812.      */
  813.     if ((buf = malloc(PFILT_CHUNKSIZE)) == NULL) {
  814.         (void) fprintf(stderr, "%s: out of memory.\n", pname);
  815.         finish(-1);
  816.     }
  817. #endif
  818.  
  819.     /*
  820.      * Set up the alarm handler.
  821.      */
  822.     (void) signal(SIGALRM, wakeup);
  823.  
  824.     /*
  825.      * Set up the alarm clock.
  826.      */
  827.     (void) bzero((char *) &itv, sizeof(struct itimerval));
  828.  
  829.     itv.it_interval.tv_sec = cycletime;
  830.     itv.it_interval.tv_usec = 0;
  831.  
  832.     itv.it_value = itv.it_interval;
  833.  
  834.     (void) setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0);
  835.  
  836.     /*
  837.      * Set the start time.
  838.       */
  839.     (void) gettimeofday(&starttime, (struct timezone *) 0);
  840.  
  841. #ifdef USE_DLPI
  842.     /*
  843.      * Flush the read queue of any packets that accumulated
  844.      * during setup time.
  845.      */
  846.     for (i=0; i < ninterfaces; i++) {
  847.         flush_dlpi(if_fd[i]);
  848.         tdrops[i] = 0;
  849.     }
  850.  
  851.     for (;;) {
  852.         FD_ZERO(&readfds);
  853.  
  854.         for (i=0; i < ninterfaces; i++)
  855.             FD_SET(if_fd[i], &readfds);
  856.  
  857.         /*
  858.          * See which nets have packets to read.
  859.          */
  860.         cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0, 0);
  861.  
  862.         if ((cc < 0) && (errno != EINTR)) {
  863.             error("select");
  864.             finish(-1);
  865.         }
  866.         if (cc == 0) {
  867.             continue;
  868.         }
  869.         
  870.         /*
  871.          * For each interface...
  872.          */
  873.         for (i=0; i < ninterfaces; i++) {
  874.             /*
  875.              * Nothing to read.
  876.              */
  877.             if (!FD_ISSET(if_fd[i], &readfds))
  878.                 continue;
  879.  
  880.             /*
  881.              * Now read packets from the dlpi device.
  882.              */
  883.             flags = 0;
  884.             strdata.len = 0;
  885.             if (getmsg(if_fd[i], NULL, &strdata, &flags) != 0)
  886.                 continue;
  887.  
  888.             bufstop = buf + strdata.len;
  889.             bp = buf;
  890.  
  891. #ifdef SUNOS5
  892.             /*
  893.              * Loop through the chunk, extracting packets.
  894.              */
  895.             while (bp < bufstop) {
  896.                 cp = bp;
  897.  
  898.                 /*
  899.                  * Get the nit header.
  900.                  */
  901.                 hdrp = (struct sb_hdr *) cp;
  902.                 cp += sizeof(struct sb_hdr);
  903.  
  904.                 int_pkt_drops += hdrp->sbh_drops - tdrops[i];
  905.                 pkt_drops += hdrp->sbh_drops - tdrops[i];
  906.                 tdrops[i] = hdrp->sbh_drops;
  907.  
  908.                 /*
  909.                  * Filter the packet.
  910.                  */
  911.                 if (if_dlt[i] == DLT_FDDI) {
  912.                     pkt_filter_fddi(cp, hdrp->sbh_msglen,
  913.                             &hdrp->sbh_timestamp);
  914.                 }
  915.                 else {
  916.                     pkt_filter_ether(cp, hdrp->sbh_msglen,
  917.                              &hdrp->sbh_timestamp);
  918.                 }
  919.  
  920.                 /*
  921.                  * Skip over this packet.
  922.                  */
  923.                 bp += hdrp->sbh_totlen;
  924.             }
  925. #else /* SUNOS5 */
  926.             /*
  927.              * It's just a packet, no buffering.
  928.              */
  929.             if (strdata.len) {
  930.                 /*
  931.                  * Since we're not on SunOS5, that means we
  932.                  * don't have DLIOCRAW, so we don't have the
  933.                  * packet frame header.  So, we need to
  934.                  * bypass that level of filtering.
  935.                  */
  936.                 pkt_dispatch(bp, strdata.len, 0,
  937.                          htons(DLPI_DEFAULTSAP), 0);
  938.             }
  939. #endif /* SUNOS5 */
  940.         }
  941. #endif /* USE_DLPI */
  942.  
  943. #ifdef USE_NIT
  944.     /*
  945.      * Flush the read queue of any packets that accumulated
  946.      * during setup time.
  947.      */
  948.     for (i=0; i < ninterfaces; i++) {
  949.         flush_nit(if_fd[i]);
  950.         tdrops[i] = 0;
  951.     }
  952.  
  953.     for (;;) {
  954.         FD_ZERO(&readfds);
  955.  
  956.         for (i=0; i < ninterfaces; i++)
  957.             FD_SET(if_fd[i], &readfds);
  958.  
  959.         /*
  960.          * See which nets have packets to read.
  961.          */
  962.         cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0, 0);
  963.  
  964.         if ((cc < 0) && (errno != EINTR)) {
  965.             error("select");
  966.             finish(-1);
  967.         }
  968.         if (cc == 0) {
  969.             continue;
  970.         }
  971.         
  972.         /*
  973.          * For each interface...
  974.          */
  975.         for (i=0; i < ninterfaces; i++) {
  976.             /*
  977.              * Nothing to read.
  978.              */
  979.             if (!FD_ISSET(if_fd[i], &readfds))
  980.                 continue;
  981.  
  982.             /*
  983.              * Now read packets from the nit device.
  984.              */
  985.             if ((cc = read(if_fd[i], buf, NIT_CHUNKSIZE)) <= 0)
  986.                 continue;
  987.  
  988.             bufstop = buf + cc;
  989.             bp = buf;
  990.  
  991.             /*
  992.              * Loop through the chunk, extracting packets.
  993.              */
  994.             while (bp < bufstop) {
  995.                 cp = bp;
  996.  
  997.                 /*
  998.                  * Get the nit header.
  999.                  */
  1000.                 hdrp = (struct nit_bufhdr *) cp;
  1001.                 cp += sizeof(struct nit_bufhdr);
  1002.  
  1003.                 /*
  1004.                  * Get the time stamp.
  1005.                  */
  1006.                 tstamp = (struct nit_iftime *) cp;
  1007.                 cp += sizeof(struct nit_iftime);
  1008.  
  1009.                 /*
  1010.                  * Get the number of dropped packets.
  1011.                  */
  1012.                 ndp = (struct nit_ifdrops *) cp;
  1013.                 cp += sizeof(struct nit_ifdrops);
  1014.  
  1015.                 int_pkt_drops += ndp->nh_drops - tdrops[i];
  1016.                 pkt_drops += ndp->nh_drops - tdrops[i];
  1017.                 tdrops[i] = ndp->nh_drops;
  1018.  
  1019.                 /*
  1020.                  * Filter the packet.
  1021.                  */
  1022. #ifdef notdef
  1023.                 /*
  1024.                  * This is how it *should* be.  But the NIT
  1025.                  * device rips off the FDDI packet header
  1026.                  * and the 802.2 LLC header, and replaces
  1027.                  * them with an ethernet packet header.
  1028.                  */
  1029.                 if (if_dlt[i] == DLT_FDDI) {
  1030.                     pkt_filter_fddi(cp, hdrp->nhb_msglen,
  1031.                             &tstamp->nh_timestamp);
  1032.                 }
  1033.                 else {
  1034.                     pkt_filter_ether(cp, hdrp->nhb_msglen,
  1035.                              &tstamp->nh_timestamp);
  1036.                 }
  1037. #else
  1038.                 /*
  1039.                  * So... we just do this instead for both
  1040.                  * ethernet and FDDI.  Strange but true.
  1041.                  */
  1042.                 pkt_filter_ether(cp, hdrp->nhb_msglen,
  1043.                          &tstamp->nh_timestamp);
  1044. #endif
  1045.  
  1046.                 /*
  1047.                  * Skip over this packet.
  1048.                  */
  1049.                 bp += hdrp->nhb_totlen;
  1050.             }
  1051.         }
  1052. #endif /* USE_NIT */
  1053.  
  1054. #ifdef USE_PFILT
  1055.     /*
  1056.      * Flush the read queue of any packets that accumulated
  1057.      * during setup time.
  1058.      */
  1059.     for (i=0; i < ninterfaces; i++)
  1060.         flush_pfilt(if_fd[i]);
  1061.  
  1062.     for (;;) {
  1063.         FD_ZERO(&readfds);
  1064.  
  1065.         for (i=0; i < ninterfaces; i++)
  1066.             FD_SET(if_fd[i], &readfds);
  1067.  
  1068.         /*
  1069.          * See which interfaces have any packets to read.
  1070.          */
  1071.         cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0, 0);
  1072.  
  1073.         if ((cc < 0) && (errno != EINTR)) {
  1074.             error("select");
  1075.             finish(-1);
  1076.         }
  1077.         if (cc == 0) {
  1078.             continue;
  1079.         }
  1080.  
  1081.         /*
  1082.          * Now read packets from the packet filter device.
  1083.          */
  1084.         for (i=0; i < ninterfaces; i++) {
  1085.             if (!FD_ISSET(if_fd[i], &readfds))
  1086.                 continue;
  1087.             
  1088.             if ((cc = read(if_fd[i], buf, PFILT_CHUNKSIZE)) < 0) {
  1089.                 lseek(if_fd[i], 0L, 0);
  1090.  
  1091.                 /*
  1092.                  * Might have read MAXINT bytes.  Try again.
  1093.                  */
  1094.                 if ((cc = read(if_fd[i], buf, PFILT_CHUNKSIZE)) < 0) {
  1095.                     error("pfilt read");
  1096.                     finish(-1);
  1097.                 }
  1098.             }
  1099.         
  1100.             bp = buf;
  1101.  
  1102.             /*
  1103.              * Loop through buffer, extracting packets.
  1104.              */
  1105.             while (cc > 0) {
  1106.                 /*
  1107.                  * Avoid alignment issues.
  1108.                  */
  1109.                 (void) bcopy(bp, &stamp, sizeof(stamp));
  1110.  
  1111.                 /*
  1112.                  * Treat entire buffer as garbage.
  1113.                  */
  1114.                 if (stamp.ens_stamplen != sizeof(stamp))
  1115.                     break;
  1116.  
  1117.                 /*
  1118.                  * Get the number of dropped packets.
  1119.                  */
  1120.                 int_pkt_drops += stamp.ens_dropped;
  1121.                 pkt_drops += stamp.ens_dropped;
  1122.  
  1123.                 /*
  1124.                  * Filter the packet.
  1125.                  */
  1126.                 datalen = stamp.ens_count;
  1127.  
  1128.                 if (datalen > truncation)
  1129.                     datalen = truncation;
  1130.  
  1131.                 if (if_dlt[i] == DLT_FDDI) {
  1132.                     /* Weird Ultrix padding */
  1133.                     pkt_filter_fddi(&(bp[sizeof(stamp) + 3]),
  1134.                             datalen,
  1135.                             &stamp.ens_tstamp);
  1136.                 }
  1137.                 else
  1138.                     pkt_filter_ether(&(bp[sizeof(stamp)]),
  1139.                              datalen,
  1140.                              &stamp.ens_tstamp);
  1141.  
  1142.                 /*
  1143.                  * Skip over this packet.
  1144.                  */
  1145.                 if (cc == (datalen + sizeof(stamp)))
  1146.                     break;
  1147.  
  1148.                 datalen = ENALIGN(datalen);
  1149.                 datalen += sizeof(stamp);
  1150.                 cc -= datalen;
  1151.                 bp += datalen;
  1152.             }
  1153.         }
  1154.  
  1155. #endif /* USE_PFILT */
  1156.  
  1157. #ifdef USE_SNOOP
  1158.     /*
  1159.      * Flush the read queue of any packets that accumulated
  1160.      * during setup time.
  1161.      */
  1162.     for (i=0; i < ninterfaces; i++) {
  1163.         flush_snoop(if_fd[i]);
  1164.         tdrops[i] = 0;
  1165.     }
  1166.  
  1167.     /*
  1168.      * Now read packets from the snooper.
  1169.      */
  1170.     for (;;) {
  1171.         int dropped;
  1172.  
  1173.         FD_ZERO(&readfds);
  1174.  
  1175.         for (i=0; i < ninterfaces; i++)
  1176.             FD_SET(if_fd[i], &readfds);
  1177.  
  1178.         /*
  1179.          * See which nets have packets to read.
  1180.          */
  1181.         cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0, 0);
  1182.  
  1183.         if ((cc < 0) && (errno != EINTR)) {
  1184.             error("select");
  1185.             finish(-1);
  1186.         }
  1187.         if (cc == 0) {
  1188.             continue;
  1189.         }
  1190.         
  1191.         /*
  1192.          * For each interface...
  1193.          */
  1194.         for (i=0; i < ninterfaces; i++) {
  1195.             /*
  1196.              * Nothing to read.
  1197.              */
  1198.             if (!FD_ISSET(if_fd[i], &readfds))
  1199.                 continue;
  1200.  
  1201.             /*
  1202.              * Now read packets from the nit device.
  1203.              */
  1204.             if ((cc = read(if_fd[i], &ep, sizeof(ep))) <= 0)
  1205.                 continue;
  1206.  
  1207.             if (do_update) {
  1208.                 /*
  1209.                  * Get the number of dropped packets.
  1210.                  */
  1211.                 if (ioctl(if_fd[i], SIOCRAWSTATS, &rs) == 0) {
  1212.                     dropped = rs.rs_snoop.ss_ifdrops +
  1213.                           rs.rs_snoop.ss_sbdrops;
  1214.  
  1215.                     int_pkt_drops += dropped - tdrops[i];
  1216.                     pkt_drops += dropped - tdrops[i];
  1217.                     tdrops[i] = dropped;
  1218.                 }
  1219.             }
  1220.  
  1221.             /*
  1222.              * Filter the packet.
  1223.              */
  1224.             if (if_dlt[i] == DLT_FDDI) {
  1225.                 /*
  1226.                  * This probably won't work.
  1227.                  */
  1228.                 pkt_filter_fddi(&ep.ether,
  1229.                         ep.snoop.snoop_packetlen,
  1230.                         &ep.snoop.snoop_timestamp);
  1231.             }
  1232.             else {
  1233.                 pkt_filter_ether(&ep.ether,
  1234.                          ep.snoop.snoop_packetlen,
  1235.                          &ep.snoop.snoop_timestamp);
  1236.             }
  1237.         }
  1238. #endif /* USE_SNOOP */
  1239.  
  1240.         tv.tv_sec = 0;
  1241.         tv.tv_usec = 0;
  1242.         FD_ZERO(&readfds);
  1243.         FD_SET(0, &readfds);
  1244.  
  1245.         /*
  1246.          * See if a command has been typed.
  1247.          */
  1248.         if (!bgflag) {
  1249.             cc = select(NFDBITS, &readfds, (fd_set *) 0,
  1250.                     (fd_set *) 0, &tv);
  1251.  
  1252.             if ((cc > 0) && FD_ISSET(0, &readfds))
  1253.                 command();
  1254.         }
  1255.     }
  1256. }
  1257.